﻿using Microsoft.EntityFrameworkCore;
using MiniErp.Entity.DataStreams;
using MiniErp.Repository.MysqlRepository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MiniErp.Repository.BaseRepository
{
    /// <summary>
    /// 仓储基类
    /// </summary>
    /// <typeparam name="TDBContext">泛型上下文（可能会使用多个数据库）</typeparam>
    /// <typeparam name="TEntity">泛型实体</typeparam>
    public class BaseRepository<TDBContext, TEntity> : IBaseRepository<TEntity>
        where TDBContext : DbContext
        where TEntity : BaseEntity
    {

        protected readonly DbSet<TEntity> _set;
        protected readonly TDBContext _dbContext;
        public BaseRepository(TDBContext dbContext)
        {
            _dbContext = dbContext;
            _set = _dbContext.Set<TEntity>();
        }
        public void AddInfo(TEntity t)
            => _set.Add(t);

        public void AddInfo(List<TEntity> t)
            => _set.AddRange(t);

        public void DeleteInfo(TEntity t)
            => _set.Remove(t);

        public void DeleteInfo(List<TEntity> t)
            => _set.RemoveRange(t);


        public void UpdateInfo(TEntity t) => _set.Update(t);

        public void UpdateInfo<Ttype>(string value, Expression<Func<Ttype, bool>> lambda = null)
        {
            if (lambda == null)
            {
                _set.Select(item => EF.Property<Ttype>(item, value));
            }
            else
            {
                _set.Select(item => EF.Property<Ttype>(item, value)).Where(lambda);
            }
        }


        public void UpdateInfo(List<TEntity> t)
            => _set.UpdateRange(t);


        public async Task<TEntity> GetInfoAsync(Expression<Func<TEntity, bool>> lambda)
            => await _set.SingleOrDefaultAsync(lambda);



        public async Task<List<TEntity>> GetInfoAsyncs(Expression<Func<TEntity, bool>> lambda = null)
            => lambda == null
            ? await _set.ToListAsync()
            : await _set.Where(lambda).ToListAsync();

        public async Task<TEntity> GetReadOnlyInfoAsync(Expression<Func<TEntity, bool>> lambda)
          => await _set.AsNoTracking().SingleOrDefaultAsync(lambda);

        public async Task<List<TEntity>> GetReadOnlyInfoAsyncs(Expression<Func<TEntity, bool>> lambda = null)
            => lambda == null
            ? await _set.AsNoTracking().ToListAsync()
            : await _set.AsNoTracking().Where(lambda).ToListAsync();


        public async Task<List<TEntity>> GetInfoAsyncs<Ttype>(int Page, int num, string value, Expression<Func<TEntity, bool>> lambda = null, bool isAsc = true)
        => lambda == null
         ? isAsc
         ? await _set
          .OrderBy(item => EF.Property<Ttype>(item, value))
          .Skip((Page - 1) * num)
          .Take(num)
          .ToListAsync()
         : await _set
          .OrderByDescending(item => EF.Property<Ttype>(item, value))
          .Skip((Page - 1) * num)
          .Take(num)
          .ToListAsync()
         : isAsc
         ? await _set
          .Where(lambda)
          .OrderBy(item => EF.Property<Ttype>(item, value))
          .Skip((Page - 1) * num)
          .Take(num)
          .ToListAsync()
         : await _set
          .Where(lambda)
          .OrderByDescending(item => EF.Property<Ttype>(item, value))
          .Skip((Page - 1) * num)
          .Take(num)
          .ToListAsync();

        public async Task<List<TEntity>> GetReadOnlyInfoAsyncs<Ttype>(int Page, int num, string value, Expression<Func<TEntity, bool>> lambda = null, bool isAsc = true)
     => lambda == null
      ? isAsc
      ? await _set
       .AsNoTracking()
       .OrderBy(item => EF.Property<Ttype>(item, value))
       .Skip((Page - 1) * num)
       .Take(num)
       .ToListAsync()
      : await _set
       .AsNoTracking()
       .OrderByDescending(item => EF.Property<Ttype>(item, value))
       .Skip((Page - 1) * num)
       .Take(num)
       .ToListAsync()
      : isAsc
      ? await _set
       .AsNoTracking()
       .Where(lambda)
       .OrderBy(item => EF.Property<Ttype>(item, value))
       .Skip((Page - 1) * num)
       .Take(num)
       .ToListAsync()
      : await _set
       .AsNoTracking()
       .Where(lambda)
       .OrderByDescending(item => EF.Property<Ttype>(item, value))
       .Skip((Page - 1) * num)
       .Take(num)
       .ToListAsync();


        public async Task<int> GetInfoNumsAsync(Expression<Func<TEntity, bool>> lambda = null)
            => lambda == null
            ? await _set.CountAsync()
            : await _set.CountAsync(lambda);


    }
}
